package world.snowcrystal.openapi.service.impl.rpc;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import world.snowcrystal.commons.exception.BusinessException;
import world.snowcrystal.commons.model.dto.rpc.CheckAccessSignatureRequest;
import world.snowcrystal.commons.model.dto.rpc.RetrieveInvokerRequest;
import world.snowcrystal.commons.model.dto.rpc.SimpleRpcResponse;
import world.snowcrystal.commons.model.entity.User;
import world.snowcrystal.commons.model.enums.ApplicationResponseStatusCode;
import world.snowcrystal.commons.service.rpc.RpcUserService;
import world.snowcrystal.openapi.mapper.UserMapper;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Optional;


@RestController
@RequestMapping("/service/user")
public class RpcUserServiceImpl implements RpcUserService {

    private static final String SALT = "wqeiprqweioprhwsdjiofhndofhn";

    private MessageDigest instance;

    private final UserMapper mapper;


    public RpcUserServiceImpl(UserMapper userMapper) {
        this.mapper = userMapper;
        try {
            this.instance = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException ignore) {
        }
    }


    private String encode(String accessKey, String secretKey) {
        return new String(Base64.getEncoder().encode(instance.digest((accessKey + secretKey + SALT).getBytes())));
    }


    @Override
    @PostMapping({"/get-user-by-access-key"})
    public User getInvoker(RetrieveInvokerRequest request) {
        String accessKey = request.getAccessKey();
        if (!(StringUtils.hasText(accessKey))) {
            throw new BusinessException(ApplicationResponseStatusCode.PARAMS_ERROR, "accessKey or secretKey is null");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("accessKey", accessKey);
        return mapper.selectOne(queryWrapper);
    }

    @Override
    @PostMapping({"/check-access-signature"})
    public SimpleRpcResponse<Boolean> checkAccessSignature(CheckAccessSignatureRequest request) {
        String accessKey = request.getAccessKey();
        Long userId = request.getUserId();
        String sign = request.getSign();

        boolean useUserId = userId != null && userId > 0;

        if ((!useUserId && !StringUtils.hasText(accessKey))) {
            throw new BusinessException(ApplicationResponseStatusCode.PARAMS_ERROR, "accessKey or userId is required");
        }
        if (!StringUtils.hasText(sign)) {
            throw new BusinessException(ApplicationResponseStatusCode.PARAMS_ERROR, "sign is required");
        }

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        QueryWrapper<User> query = queryWrapper
                .eq("id", userId)
                .or()
                .eq("accessKey", accessKey);
        User user = mapper.selectOne(query);
        SimpleRpcResponse.SimpleRpcResponseBuilder<Boolean> builder = SimpleRpcResponse.<Boolean>builder();
        if (user == null) {
//            throw new BusinessException(ApplicationResponseStatusCode.NOT_FOUND_ERROR, "user is not exist");
            return builder.data(false).build();
        }
        String secretKey = Optional.ofNullable(user.getSecretKey()).orElse("");
        String encode = encode(accessKey, secretKey);
        return builder.data(encode.equals(sign)).build();
    }
}
